package com.dsg.service.apply.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dsg.common.security.SystemAuthorizingUser;
import com.dsg.common.util.DateUtils;
import com.dsg.common.util.FileUtils;
import com.dsg.common.util.SingletonLoginUtils;
import com.dsg.common.util.UUIDGenerator;
import com.dsg.common.util.toolbox.CollectionUtil;
import com.dsg.common.util.toolbox.StringUtil;
import com.dsg.dao.apply.DeductOneYuanMapper;
import com.dsg.entity.account.DsgAccountSetting;
import com.dsg.entity.apply.DsgApplyPay;
import com.dsg.entity.apply.DsgApplyStatus;
import com.dsg.service.DsgServiceImpl;
import com.dsg.service.account.IDsgAccountCardService;
import com.dsg.service.account.IDsgAccountSettingService;
import com.dsg.service.apply.IDeductOneYuanService;
import com.dsg.service.apply.IDsgApplyCardService;
import com.dsg.service.apply.IDsgApplyPayService;
import com.dsg.service.apply.IDsgApplyStatusService;
import com.dsg.support.LeveldbAccess;
import com.dsg.util.Constant;
import com.dsg.util.DsgUtils;
import com.dsg.util.EasyExcelUtils;
import com.dsg.util.RRException;
import com.dsg.workflow.WorkflowService3;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.zip.Zip64Mode;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @program: erp
 * @description: 扣1元
 * @author: 賴利榮
 * @create: 2020-10-09 19:32
 */
@Slf4j
@Service
public class DeductOneYuanServiceImpl extends DsgServiceImpl<DeductOneYuanMapper, DsgApplyPay> implements IDeductOneYuanService {

    @Autowired
    private IDsgApplyStatusService dsgApplyStatusService;
    @Autowired
    private IDsgApplyCardService dsgApplyCardService;
    @Autowired
    private IDsgAccountCardService dsgAccountCardService;
    @Autowired
    private IDsgApplyPayService dsgApplyPayService;
    @Autowired
    private IDsgAccountSettingService dsgAccountSettingService;
    @Autowired
    private LeveldbAccess leveldbAccess;

    @Override
    public Page<DsgApplyPay> selectDeductOneYuanList(Page<DsgApplyPay> page, DsgApplyPay dsgApplyPay) {
        dsgApplyPay.setUserId(SingletonLoginUtils.getSystemUserId());
        return page.setRecords(baseMapper.selectDeductOneYuanList(page, dsgApplyPay));
    }

    @Override
    public List<DsgApplyPay> selectDeductOneYuanList(DsgApplyPay dsgApplyPay) {
        return baseMapper.selectDeductOneYuanList(dsgApplyPay);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateDEDUStatus(String idList, Integer isDedu) {
        if (StringUtil.isEmpty(idList)) {
            throw new RRException("主鍵不能為空！");
        }
        QueryWrapper<DsgApplyStatus> queryWrapper = new QueryWrapper();
        queryWrapper.eq("IS_DEDU", DsgApplyStatus.AppStatus.no.getCode());
//        queryWrapper.eq("IS_DEDU", DsgApplyStatus.AppStatus.haveInHand.getCode());
        queryWrapper.in("OID", Arrays.asList(idList.split(",")));
        List<DsgApplyStatus> dsgApplyStatusList = dsgApplyStatusService.list(queryWrapper);
        if (CollectionUtil.isNotEmpty(dsgApplyStatusList)) {
            dsgApplyStatusList.forEach(I -> {
                I.setIsDedu(isDedu);
            });
            dsgApplyStatusService.updateBatchById(dsgApplyStatusList);
        }




        /*if (CollectionUtil.isNotEmpty(dsgApplyStatusList)) {
            List<String> keyList = new ArrayList<>();
            String oid = UUIDGenerator.getUUID();
            SystemAuthorizingUser sysUser = SingletonLoginUtils.getSystemUser();
            try {
                //查詢油咭資料
                QueryWrapper<DsgApplyCard> cardQueryWrapper = new QueryWrapper<>();
                cardQueryWrapper.eq("ENT_CODE", sysUser.getOrgCode());
                cardQueryWrapper.in("OID", dsgApplyStatusList.stream().map(DsgApplyStatus::getCardId).collect(Collectors.toList()));
                List<DsgApplyCard> dsgApplyCardList = dsgApplyCardService.list(cardQueryWrapper);
                dsgApplyCardList.forEach(I -> {
                    String key = leveldbAccess.genCacheKey(oid, DsgApplyCard.class.getSimpleName(), I.getCardNo());
                    leveldbAccess.put(key, I);
                    keyList.add(key);
                });
                //取油咭總賬并缓存
                QueryWrapper<DsgAccountCard> accountCardQueryWrapper = new QueryWrapper<>();
                accountCardQueryWrapper.eq("ENT_CODE", sysUser.getOrgCode());
                List<DsgAccountCard> dsgAccountCardList = dsgAccountCardService.list(accountCardQueryWrapper);
                dsgAccountCardList.forEach(I -> {
                    String key = leveldbAccess.genCacheKey(oid, DsgAccountCard.class.getSimpleName(), I.getCardNo());
                    leveldbAccess.put(key, I);
                    keyList.add(key);
                });
                //取繳款資料并缓存
                QueryWrapper<DsgApplyPay> payQueryWrapper = new QueryWrapper<>();
                payQueryWrapper.eq("ENT_CODE", sysUser.getOrgCode());
                payQueryWrapper.in("OID", dsgApplyCardList.stream().map(DsgApplyCard::getPayId).collect(Collectors.toList()));
                List<DsgApplyPay> dsgApplyPayList = dsgApplyPayService.list(payQueryWrapper);
                dsgApplyPayList.forEach(I -> {
                    String key = leveldbAccess.genCacheKey(oid, DsgApplyPay.class.getSimpleName(), I.getOid());
                    leveldbAccess.put(key, I);
                    keyList.add(key);
                });
                //取繳款資料并缓存
                QueryWrapper<DsgAccountSetting> settingQueryWrapper = new QueryWrapper<>();
                settingQueryWrapper.eq("ENT_CODE", sysUser.getOrgCode());
                settingQueryWrapper.in("ACCOUNT_NO", dsgApplyPayList.stream().map(DsgApplyPay::getAccountNo).collect(Collectors.toList()));
                List<DsgAccountSetting> dsgAccountSettingList = dsgAccountSettingService.list(settingQueryWrapper);
                dsgAccountSettingList.forEach(I -> {
                    String key = leveldbAccess.genCacheKey(oid, DsgAccountSetting.class.getSimpleName(), I.getAccountNo());
                    leveldbAccess.put(key, I);
                    keyList.add(key);
                });
                dsgApplyCardList.clear();
                dsgAccountCardList.clear();
                dsgApplyPayList.clear();
                dsgAccountSettingList.clear();
                for (DsgApplyStatus dsgApplyStatus : dsgApplyStatusList) {
                    dsgApplyStatus.setIsDedu(DsgApplyStatus.AppStatus.yes.getCode());
                    String key = leveldbAccess.genCacheKey(oid, DsgAccountCard.class.getSimpleName(), dsgApplyStatus.getCarNo());
                    DsgAccountCard dsgAccountCard = leveldbAccess.get(key);
                    if (dsgAccountCard != null) {
                        DsgAccountTrade dsgAccountTrade = new DsgAccountTrade();
                        dsgAccountTrade.setOid(UUIDGenerator.getUUID());
                        dsgAccountTrade.setCusNo(dsgAccountCard.getCusNo());
                        dsgAccountTrade.setCardNo(dsgAccountCard.getCardNo());
                        key = leveldbAccess.genCacheKey(oid, DsgApplyCard.class.getSimpleName(), dsgAccountCard.getCardNo());
                        DsgApplyCard dsgApplyCard = leveldbAccess.get(key);
                        if (dsgApplyCard != null) {
                            key = leveldbAccess.genCacheKey(oid, DsgApplyPay.class.getSimpleName(), dsgApplyCard.getOid());
                            DsgApplyPay dsgApplyPay = leveldbAccess.get(key);
                            if (dsgApplyPay != null) {
                                key = leveldbAccess.genCacheKey(oid, DsgAccountSetting.class.getSimpleName(), dsgApplyPay.getAccountNo());
                                DsgAccountSetting dsgAccountSetting = leveldbAccess.get(key);
                                if (dsgAccountSetting != null) {
                                    dsgAccountTrade.setCountMode(dsgAccountSetting.getPayMethod());
                                }
                            }
                        }
                        dsgAccountTrade.setInOut("OUT");
                        dsgAccountTrade.setTranItem(DsgAccountTrade.AppStatus.deductOneYuan.getCode());
                        dsgAccountTrade.setTranCode(SnowflakeKeyWorker.nextStrId());

                    }
                }
            } finally {
                if (CollectionUtil.isNotEmpty(keyList)) {
                    keyList.forEach(I -> leveldbAccess.delete(I));
                }
            }
        }*/
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void download(HttpServletResponse response) throws Exception {
        SystemAuthorizingUser user = SingletonLoginUtils.getSystemUser();
        DsgApplyPay dsgApplyPay = new DsgApplyPay();
        dsgApplyPay.setDedStatusList("0,1");
        dsgApplyPay.setNodeName(WorkflowService3.NODE_DEDUCT_ONE);
        dsgApplyPay.setEntCode(user.getOrgCode());
        dsgApplyPay.setUserId(user.getUserId());
        List<DsgApplyPay> dsgApplyPayList = selectDeductOneYuanList(dsgApplyPay);
        Map<String, List<DsgApplyPay>> payMap = dsgApplyPayList.stream().collect(Collectors.groupingBy(I -> I.getAccountNo()));
        if (CollectionUtil.isNotEmpty(payMap)) {
            List<String> keyList = new ArrayList<>();
            String oid = UUIDGenerator.getUUID();
            try {
                //取繳款資料并缓存
                QueryWrapper<DsgAccountSetting> settingQueryWrapper = new QueryWrapper<>();
                settingQueryWrapper.eq("ENT_CODE", user.getOrgCode());
                List<DsgAccountSetting> dsgAccountSettingList = dsgAccountSettingService.list(settingQueryWrapper);
                dsgAccountSettingList.forEach(I -> {
                    String key = leveldbAccess.genCacheKey(oid, DsgAccountSetting.class.getSimpleName(), I.getAccountNo());
                    leveldbAccess.put(key, I);
                    keyList.add(key);
                });
                response.setContentType("application/zip");
                response.setCharacterEncoding("utf-8");
                String fileName = "過1元_" + user.getInputCopName() + "_" + DateUtils.getStringDate() + ".zip";
                response.setHeader("Content-disposition", "attachment; filename=" + URLEncoder.encode(fileName, "utf-8"));
                OutputStream out = response.getOutputStream();
                //壓縮
                ZipArchiveOutputStream zous = new ZipArchiveOutputStream(out);
                zous.setUseZip64(Zip64Mode.AsNeeded);
                for (String payKey : payMap.keySet()) {
                    List<DsgApplyPay> dsgApplyPays = payMap.get(payKey);
                    if (CollectionUtil.isNotEmpty(dsgApplyPays)) {
                        String key = leveldbAccess.genCacheKey(oid, DsgAccountSetting.class.getSimpleName(), payKey);
                        DsgAccountSetting dsgAccountSetting = leveldbAccess.get(key);
                        if (dsgAccountSetting != null) {
                            dsgApplyPays.forEach(I -> I.setMerchantNo(dsgAccountSetting.getMerchantNo()));
                            switch (dsgAccountSetting.getPayMethod()) {
                                case Constant.PAY_TYPE_CDC:
                                    //暂时所有银行用同一格式 TODO
//                                    switch (dsgAccountSetting.getBankId()) {
//                                        case "Bea":
                                    downloadBea(Constant.PAY_TYPE_CDC, zous, dsgApplyPays.get(0));
//                                            break;
//                                        case "Dbs":
//                                            break;
//                                        case "HangSeng":
//                                            break;
//                                        case "Ocbc":
//                                            break;
//                                        default:
//                                            break;
//                                    }
                                    break;
                                case Constant.PAY_TYPE_ATP:
                                    downloadBea(Constant.PAY_TYPE_ATP, zous, dsgApplyPays.get(0));
//                                            throw new RRException("ATP過1元開發中");

                                default:
                                    break;
                            }
                        }
                    }
                }
                zous.close();
            } finally {
                if (CollectionUtil.isNotEmpty(keyList)) {
                    keyList.forEach(I -> leveldbAccess.delete(I));
                }
            }
        }
    }

    /**
     * @param zous
     * @param pay
     * @throws Exception
     */
    private void downloadBea(String type, ZipArchiveOutputStream zous, DsgApplyPay pay) throws Exception {
        // 分頁
        Page page = new Page();
        List<OrderItem> orderItemList = new ArrayList<>();
        orderItemList.add(new OrderItem().setColumn("d.CREATE_TIME").setAsc(false));
        page.setOrders(orderItemList);
        page.setSize(EasyExcelUtils.PER_WRITE_ROW_COUNT);
        SystemAuthorizingUser user = SingletonLoginUtils.getSystemUser();
        String templateFileName = FileUtils.getExcelTemplatePath("bankABea.xlsx");
        String fileName = user.getInputCopName() + "_" + DateUtils.getStringDate() + "_Bea.xlsx";
        DsgApplyPay dsgApplyPay = new DsgApplyPay();
        dsgApplyPay.setAccountNo(pay.getAccountNo());
        dsgApplyPay.setEntCode(user.getOrgCode());
        dsgApplyPay.setMerchantNo(pay.getMerchantNo());
        dsgApplyPay.setDedStatusList("0,1");
        dsgApplyPay.setNodeName(WorkflowService3.NODE_DEDUCT_ONE);
        dsgApplyPay.setFlag("1");
        if (Constant.PAY_TYPE_ATP.equals(type)) {
            dsgApplyPay.setPayStatus(DsgApplyStatus.AppStatus.haveInHand.getCode());
        }
        this.writerFill(zous, page, dsgApplyPay, templateFileName, fileName);
        dsgApplyPay.setFlag("0");
        templateFileName = FileUtils.getExcelTemplatePath("bankANonbea.xlsx");
        fileName = user.getInputCopName() + "_" + DateUtils.getStringDate() + "_Nonbea.xlsx";
        this.writerFill(zous, page, dsgApplyPay, templateFileName, fileName);

    }

    /**
     * 生成Excel文件添加到壓縮文件
     *
     * @param zous
     * @param page
     * @param templateFileName 模板文件
     * @param fileName         生成文件
     * @throws Exception
     */
    private void writerFill(ZipArchiveOutputStream zous, Page page, DsgApplyPay dsgApplyPay,
                            String templateFileName, String fileName) throws Exception {
        int currentPage = 0;
        List<DsgApplyPay> dsgApplyPayList;
        BigDecimal tranValue = BigDecimal.ZERO;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ExcelWriter excelWriter = EasyExcel.write(bos).withTemplate(templateFileName).build();
        WriteSheet writeSheet = EasyExcel.writerSheet(0).build();
        do {
            page.setCurrent(++currentPage);
            dsgApplyPayList = selectDeductOneYuanList(page, dsgApplyPay).getRecords();
            if (CollectionUtil.isNotEmpty(dsgApplyPayList)) {
                List<DsgApplyPay> upDsgApplyPay = new ArrayList<>();
                for (DsgApplyPay pay : dsgApplyPayList) {
                    tranValue = tranValue.add(BigDecimal.ONE);
                    pay.setTranValue(BigDecimal.ONE);
//                    pay.setBankCode(pay.getAccountNo());
                    pay.setMerchantNo(dsgApplyPay.getMerchantNo());
                    pay.setCusNo(pay.getCusNo() + "-" + DsgUtils.getUUID());
                    DsgApplyPay dap = new DsgApplyPay();
                    dap.setOid(pay.getOid());
                    dap.setDedStatus(DsgApplyStatus.AppStatus.haveInHand.getCode());
                    if (dsgApplyPay.getPayStatus() != null) {
                        dap.setPayStatus(dsgApplyPay.getPayStatus());
                    }
                    dap.setDdaNumber(pay.getCusNo());
                    upDsgApplyPay.add(dap);
                }
                excelWriter.fill(dsgApplyPayList, writeSheet);
                log.info("寫銀行過數據數據{}条", dsgApplyPayList.size());
                //回填狀態
                dsgApplyPayService.updateBatchById(upDsgApplyPay);
            }
        } while (CollectionUtil.isNotEmpty(dsgApplyPayList) && dsgApplyPayList.size() == EasyExcelUtils.PER_WRITE_ROW_COUNT);
        if (CollectionUtil.isNotEmpty(dsgApplyPayList)) {
            dsgApplyPayList.clear();
            dsgApplyPayList.add(new DsgApplyPay());
            DsgApplyPay pay = new DsgApplyPay();
            pay.setBankCode("Total:");
            pay.setTranValue(tranValue);
            dsgApplyPayList.add(pay);
            excelWriter.fill(dsgApplyPayList, writeSheet);
            excelWriter.finish();
            //设置文件名
            ArchiveEntry entry = new ZipArchiveEntry(fileName);
            zous.putArchiveEntry(entry);
            zous.write(bos.toByteArray());
            zous.closeArchiveEntry();
            bos.close();
        }
    }

    @Override
    public List<DsgApplyStatus> selectDsgApplyStatus(String entCode, List<String> list) {
        return baseMapper.selectDsgApplyStatus(entCode, list);
    }
}
